home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / src / switchmenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-04-26  |  8.9 KB  |  367 lines

  1. /* 
  2.  *  Window Maker window manager
  3.  * 
  4.  *  Copyright (c) 1997 Shige Abe and 
  5.  *               Alfredo K. Kojima
  6.  * 
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
  20.  *  USA.
  21.  */
  22.  
  23.  
  24. #include "wconfig.h"
  25.  
  26. #ifndef LITE
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31.  
  32. #include <X11/Xlib.h>
  33. #include <X11/Xutil.h>
  34.  
  35. #include "WindowMaker.h"
  36. #include "window.h"
  37. #include "actions.h"
  38. #include "client.h"
  39. #include "funcs.h"
  40. #include "stacking.h"
  41. #include "workspace.h"
  42. #include "framewin.h"
  43.  
  44. /********* Global Variables *******/
  45. extern WPreferences wPreferences;
  46. extern Time LastTimestamp;
  47.  
  48.  
  49. /*
  50.  * FocusWindow
  51.  *
  52.  *  - Needs to check if already in the right workspace before
  53.  *    calling wChangeWorkspace?
  54.  *
  55.  *  Order:
  56.  *    Switch to correct workspace
  57.  *    Unshade if shaded
  58.  *    If iconified then deiconify else focus/raise.
  59.  */
  60. static void
  61. focusWindow(WMenu *menu, WMenuEntry *entry)
  62. {
  63.     WWindow *wwin;
  64.     WScreen *scr;
  65.     int x, y, move=0;
  66.  
  67.     wwin = (WWindow*)entry->clientdata;
  68.     scr = wwin->screen_ptr;
  69.  
  70.     wMakeWindowVisible(wwin);
  71.  
  72.     x = wwin->frame_x;
  73.     y = wwin->frame_y;
  74.         
  75.     /* bring window back to visible area */
  76.     move = wScreenBringInside(scr, &x, &y, wwin->frame->core->width, 
  77.                   wwin->frame->core->height);
  78.  
  79.     if (move) {
  80.     wWindowConfigure(wwin, x, y, wwin->client.width, wwin->client.height);
  81.     }
  82. }
  83.  
  84. /*
  85.  *
  86.  * Open switch menu 
  87.  *
  88.  */
  89. void 
  90. OpenSwitchMenu(WScreen *scr, int x, int y, int keyboard)
  91. {
  92.     WMenu *switchmenu = scr->switch_menu;
  93.     WWindow *wwin;
  94.  
  95.     if (switchmenu) {
  96.     if (switchmenu->flags.mapped) {
  97.         if (!switchmenu->flags.buttoned) {
  98.         wMenuUnmap(switchmenu);
  99.         } else {
  100.         wRaiseFrame(switchmenu->frame->core);
  101.         
  102.         if (keyboard)
  103.             wMenuMapAt(switchmenu, 0, 0, True);
  104.         else
  105.             wMenuMapCopyAt(switchmenu, 
  106.                    x-switchmenu->frame->core->width/2, y);
  107.         }
  108.     } else {
  109.         wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2, y,
  110.                keyboard);
  111.     }
  112.     return;
  113.     }
  114.     switchmenu = wMenuCreate(scr,_("Windows"),True);
  115.     scr->switch_menu = switchmenu;
  116.     
  117.     
  118.     wwin = scr->focused_window;
  119.     while (wwin) {
  120.     UpdateSwitchMenu(scr, wwin, ACTION_ADD);
  121.  
  122.         wwin = wwin->prev;
  123.     }
  124.     
  125.     if (switchmenu) {
  126.     if (!switchmenu->flags.realized)
  127.         wMenuRealize(switchmenu);
  128.     wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2, y, 
  129.            keyboard);
  130.     }
  131. }
  132.  
  133.  
  134. static int
  135. menuIndexForWindow(WMenu *menu, WWindow *wwin, int old_pos)
  136. {
  137.     int idx;
  138.  
  139.     if (menu->entry_no == 0)
  140.     return -1;
  141.  
  142. #define WS(i)  ((WWindow*)menu->entries[i]->clientdata)->frame->workspace
  143.     if (old_pos >= 0) {
  144.     if (WS(old_pos) >= wwin->frame->workspace
  145.         && (old_pos == 0 || WS(old_pos-1) <= wwin->frame->workspace)) {
  146.         return old_pos;
  147.     }
  148.     }
  149. #undef WS
  150.  
  151.     for (idx = 0; idx < menu->entry_no; idx++) {
  152.     WWindow *tw = (WWindow*)menu->entries[idx]->clientdata;
  153.  
  154.     if (!IS_OMNIPRESENT(tw) 
  155.         && tw->frame->workspace > wwin->frame->workspace) {
  156.         break;
  157.     }
  158.     }
  159.  
  160.     return idx;
  161. }
  162.  
  163.  
  164. /*
  165.  * Update switch menu
  166.  */
  167. void 
  168. UpdateSwitchMenu(WScreen *scr, WWindow *wwin, int action)
  169. {
  170.     WMenu *switchmenu = scr->switch_menu;
  171.     WMenuEntry *entry;
  172.     char title[MAX_MENU_TEXT_LENGTH+6];
  173.     int i;
  174.     int checkVisibility = 0;
  175.  
  176.     if (!wwin->screen_ptr->switch_menu)
  177.       return;
  178.     /*
  179.      *  This menu is updated under the following conditions:
  180.      *
  181.      *    1.  When a window is created.
  182.      *    2.  When a window is destroyed.
  183.      *
  184.      *    3.  When a window changes it's title.
  185.      *       4.  When a window changes its workspace.
  186.      */
  187.     if (action == ACTION_ADD) {
  188.     char *t;
  189.     int idx;
  190.  
  191.     if (wwin->flags.internal_window || WFLAGP(wwin, skip_window_list))
  192.         return;
  193.         
  194.     if (wwin->frame->title)
  195.       sprintf(title, "%s", wwin->frame->title);
  196.     else
  197.       sprintf(title, "%s", DEF_WINDOW_TITLE);
  198.     t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
  199.  
  200.     if (IS_OMNIPRESENT(wwin))
  201.         idx = -1;
  202.     else {
  203.         idx = menuIndexForWindow(switchmenu, wwin, -1);
  204.     }
  205.     
  206.     entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
  207.     free(t);
  208.  
  209.     entry->flags.indicator = 1;
  210.     entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH+8);
  211.     if (IS_OMNIPRESENT(wwin))
  212.         sprintf(entry->rtext, "[*]");
  213.     else
  214.         sprintf(entry->rtext, "[%s]", 
  215.             scr->workspaces[wwin->frame->workspace]->name);
  216.  
  217.     if (wwin->flags.hidden) {
  218.         entry->flags.indicator_type = MI_HIDDEN;
  219.         entry->flags.indicator_on = 1;
  220.     } else if (wwin->flags.miniaturized) {
  221.         entry->flags.indicator_type = MI_MINIWINDOW;
  222.         entry->flags.indicator_on = 1;
  223.     } else if (wwin->flags.focused) {
  224.         entry->flags.indicator_type = MI_DIAMOND;
  225.         entry->flags.indicator_on = 1;
  226.     } else if (wwin->flags.shaded) {
  227.         entry->flags.indicator_type = MI_SHADED;
  228.         entry->flags.indicator_on = 1;
  229.     }
  230.  
  231.     wMenuRealize(switchmenu);
  232.     checkVisibility = 1;
  233.     } else {
  234.     char *t;
  235.     for (i=0; i<switchmenu->entry_no; i++) {
  236.         entry = switchmenu->entries[i];
  237.         /* this is the entry that was changed */
  238.         if (entry->clientdata == wwin) {
  239.         switch (action) {
  240.          case ACTION_REMOVE:
  241.             wMenuRemoveItem(switchmenu, i);
  242.             wMenuRealize(switchmenu);
  243.             checkVisibility = 1;
  244.             break;
  245.             
  246.          case ACTION_CHANGE:
  247.             if (entry->text)
  248.               free(entry->text);
  249.             
  250.             if (wwin->frame->title)
  251.               sprintf(title, "%s", wwin->frame->title);
  252.             else
  253.               sprintf(title, "%s", DEF_WINDOW_TITLE);
  254.  
  255.             t = ShrinkString(scr->menu_entry_font, title, 
  256.                      MAX_WINDOWLIST_WIDTH);
  257.             entry->text = t;
  258.  
  259.             wMenuRealize(switchmenu);
  260.             checkVisibility = 1;
  261.             break;
  262.  
  263.          case ACTION_CHANGE_WORKSPACE:
  264.             if (entry->rtext) {
  265.             int idx = -1;
  266.             char *t, *rt;
  267.             int it, ion;
  268.             
  269.             if (IS_OMNIPRESENT(wwin)) {
  270.                 sprintf(entry->rtext, "[*]");
  271.             } else {
  272.                 sprintf(entry->rtext, "[%s]", 
  273.                     scr->workspaces[wwin->frame->workspace]->name);
  274.             }
  275.  
  276.             rt = entry->rtext;
  277.             entry->rtext = NULL;
  278.             t = entry->text;
  279.             entry->text = NULL;
  280.             
  281.             it = entry->flags.indicator_type;
  282.             ion = entry->flags.indicator_on;
  283.  
  284.             wMenuRemoveItem(switchmenu, i);
  285.  
  286.             if (!IS_OMNIPRESENT(wwin) && idx < 0) {
  287.                 idx = menuIndexForWindow(switchmenu, wwin, i);
  288.             }
  289.  
  290.             entry = wMenuInsertCallback(switchmenu, idx, t,
  291.                             focusWindow, wwin);
  292.             free(t);
  293.             entry->rtext = rt;
  294.             entry->flags.indicator = 1;
  295.             entry->flags.indicator_type = it;
  296.             entry->flags.indicator_on = ion;
  297.             }
  298.             wMenuRealize(switchmenu);
  299.             checkVisibility = 1;
  300.             break;
  301.  
  302.  
  303.          case ACTION_CHANGE_STATE:
  304.             if (wwin->flags.hidden) {
  305.             entry->flags.indicator_type = MI_HIDDEN;
  306.             entry->flags.indicator_on = 1;
  307.             } else if (wwin->flags.miniaturized) {
  308.             entry->flags.indicator_type = MI_MINIWINDOW;
  309.             entry->flags.indicator_on = 1;
  310.             } else if (wwin->flags.shaded && !wwin->flags.focused) {
  311.             entry->flags.indicator_type = MI_SHADED;
  312.             entry->flags.indicator_on = 1;
  313.             } else {
  314.             entry->flags.indicator_on = wwin->flags.focused;
  315.             entry->flags.indicator_type = MI_DIAMOND;
  316.             }
  317.             break;
  318.         }
  319.         break;
  320.         }
  321.     }
  322.     }
  323.     if (checkVisibility) {
  324.         int tmp;
  325.  
  326.         tmp = switchmenu->frame->top_width + 5;
  327.         /* if menu got unreachable, bring it to a visible place */
  328.         if (switchmenu->frame_x < tmp - (int)switchmenu->frame->core->width) {
  329.             wMenuMove(switchmenu, tmp - (int)switchmenu->frame->core->width,
  330.                       switchmenu->frame_y, False);
  331.         }
  332.     }
  333.     wMenuPaint(switchmenu);
  334. }
  335.  
  336.  
  337.  
  338. void
  339. UpdateSwitchMenuWorkspace(WScreen *scr, int workspace)
  340. {
  341.     WMenu *menu = scr->switch_menu;
  342.     int i;
  343.     WWindow *wwin;
  344.     
  345.     if (!menu)
  346.     return;
  347.     
  348.     for (i=0; i<menu->entry_no; i++) {
  349.     wwin = (WWindow*)menu->entries[i]->clientdata;
  350.  
  351.     if (wwin->frame->workspace==workspace 
  352.         && !IS_OMNIPRESENT(wwin)) {
  353.         if (IS_OMNIPRESENT(wwin))
  354.         sprintf(menu->entries[i]->rtext, "[*]");
  355.         else
  356.         sprintf(menu->entries[i]->rtext, "[%s]", 
  357.             scr->workspaces[wwin->frame->workspace]->name);
  358.         menu->flags.realized = 0;
  359.     }
  360.     }
  361.     if (!menu->flags.realized)
  362.     wMenuRealize(menu);
  363. }
  364.  
  365.  
  366. #endif /* !LITE */
  367.